﻿using ICSharpCode.AvalonEdit.Highlighting;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace NFox.Pyeditor.Types
{
    public class KeywordList: IEnumerable<TypeBase>
    {

        public List<Statement> Statements { get; private set; }

        public List<Valuetype> Builtins { get; private set; }

        public List<Valuetype> Variants { get; private set; }

        public KeywordList()
        {
            Clear();
        }

        public void Clear()
        {
            Statements = new List<Statement>();
            Builtins = new List<Valuetype>();
            Variants = new List<Valuetype>();
        }

        public void AddStatement(string key)
        {
            Statements.Add(new Statement(key));
        }

        public void AddStatement(Statement item)
        {
            Statements.Add(item);
        }

        public void AddBuiltin(string key, object obj)
        {
            AddBuiltin(Valuetype.GetValue(key, obj));
        }

        public void AddBuiltin(Valuetype item)
        {
            Builtins.Add(item);
        }

        public void AddVariant(string key, object obj)
        {
            AddVariant(Valuetype.GetValue(key, obj));
        }

        public void AddVariant(Valuetype item)
        {
            Variants.Add(item);
        }

        public void SetVariants(IEnumerable<Valuetype> items)
        {
            Variants = items.ToList();
        }


        public Valuetype GetObject(string key, Stack<string> names)
        {
            if (Statements.Exists(s => s.Text == key))
                return null;
            var t = Builtins.FirstOrDefault(w => w.Text == key);
            if(t == null)
                t = Variants.FirstOrDefault(w => w.Text == key);

            while (names.Count > 0)
            {
                if (t == null)
                    return t;
                t = t.GetItem(names.Pop());
            }
            return t;
        }

        public IEnumerable<TypeBase> GetProperties(Valuetype type)
        {
            return type.GetItems();
        }

        public IEnumerator<TypeBase> GetEnumerator()
        {
            foreach (var item in Statements)
                yield return item;
            foreach (var item in Builtins)
                yield return item;
            foreach (var item in Variants)
                yield return item;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        Regex CreateKeywordsRegex(IEnumerable<string> words)
        {
            const RegexOptions opts = RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture;
            return new Regex($"\\b(?>{string.Join("|", words.OrderByDescending(s => s))})\\b", opts);
        }

        public void MakeHighlighting()
        {
            var hc = HighlightingManager.Instance.GetDefinition("Python");
            
            var sr = hc.MainRuleSet.Rules[2];
            sr.Regex = CreateKeywordsRegex(Statements.Select(v => v.Text));

            var br = new HighlightingRule();
            br.Color = hc.GetNamedColor("Builtin");
            br.Regex = CreateKeywordsRegex(Builtins.Select(v => v.Text)); 
            hc.MainRuleSet.Rules.Add(br);
        }

        public IEnumerable<Runtime.TreeListItemViewModel> Children
        {
            get
            {
                foreach (var value in Variants)
                    yield return new Runtime.TreeListItemViewModel(value);
            }
        }

    }
}
